/*
 * This file is part of SSHTTPD.
 *
 * SSHTTPD is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SSHTTPD is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @file
 * Parses user requests into sorted structures and does protocol compliance
 * checks on them. 
 */

/* Application level includes. */
#include "include/request.h"
#include "include/utils.h"
#include "include/file.h"
#include "include/socket.h"
#include "include/response.h"

/* System level includes. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/** 
 * Check a http header for null fields.
 * @param header Header structure to check. 
 * @return 0 if null, 1 if ok.
 */
static int reqchk(const httpr_t *header) {
	if(header->request == NULL)
		return 0;
	if(header->url == NULL)
		return 0;
	else
		return 1;
}

/**
 * Convert a http request in string form to a defined integer value.
 * @param request String to get integer value for. 
 * @return Integer value of string as defined in a macro.
 * @see REQ_GET, REQ_ERROR, REQ_HEADER, REQ_POST
 */
static int reqtype(const char *request) {
	if(request == NULL)
		return REQ_ERROR;
	else if(strcmp(request, "GET") == 0)
		return REQ_GET;
	else if(strcmp(request, "HEADER") == 0)
		return REQ_HEADER;
	else if(strcmp(request, "POST") == 0)
		return REQ_POST;
	else
		return REQ_ERROR;
}

httpr_t *reqparse(const char *request) {
	httpr_t *header;
	char *buffer;
	
	if(!(header = malloc(sizeof *header)))
		return NULL;

	/* Copy the request into our own buffer, as we are going to destroy the 
	 * string for normal use. */
	if(!(buffer = malloc(strlen(request) + 1))) {
		event(EPROB, "malloc() in httpparse()");
		return NULL;
	}
	strcpy(buffer, request);
	
	/* Allocate a new header and parse the http request. 
	 * We can assign our struct char pointers the result of strtok as
	 * it simply breaks our buffer up into seperate logical strings with 
	 * \0 while keeping it all in the original buffer.
	 * REQ /URL VER/0.0\n
	 * get the first 2 tokens split by ' ' than VER which ends with \n*/
	header->request = strtok(buffer, " \r\n");
	header->url = strtok(NULL, " \r\n");
	header->ver = strtok(NULL, " \r\n" );
	
	event(ELOG, "parsed header = request:(%s) url:(%s) ver:(%s)", SAFEPSTR(header->request), SAFEPSTR(header->url), SAFEPSTR(header->ver));
	
	/* We keep a reference to the memory we allocated for the string
	 * so it can be freed later. */
	header->bptr = buffer;
	
	/* Mark the request as invalid if it fails reqchk. */
	if(!reqchk(header))
		header->request = NULL;
	
	header->reqcode = reqtype(header->request);
	return header;
}

void destroyrequest(httpr_t *req) {
	free(req->bptr);
	free(req);
}

